import alibabacloud_oss_v2 as oss
import os
import librosa
import soundfile as sf

import json
import time
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest





def read_txt_file(file_path, encoding='utf-8'):
    """
    读取txt文件的完整函数
    """
    try:
        with open(file_path, 'r', encoding=encoding) as file:
            content = file.read()
        return content
    except FileNotFoundError:
        print(f"文件不存在: {file_path}")
        return None
    except Exception as e:
        print(f"读取文件时出错: {e}")
        return None


def read_txt_lines(file_path, encoding='utf-8'):
    """
    逐行读取txt文件
    """
    try:
        with open(file_path, 'r', encoding=encoding) as file:
            lines = [line.strip() for line in file if line.strip()]  # 去除空行
        return lines
    except FileNotFoundError:
        print(f"文件不存在: {file_path}")
        return []
    except Exception as e:
        print(f"读取文件时出错: {e}")
        return []


def convert_to_16k_librosa(input_file, output_file):
    """
    使用 librosa 将音频转换为 16kHz

    Args:
        input_file: 输入音频文件路径
        output_file: 输出音频文件路径
    """
    try:
        # 加载音频文件，保持原始采样率
        audio, original_sr = librosa.load(input_file, sr=None)

        print(f"原始音频信息:")
        print(f"  采样率: {original_sr} Hz")
        print(f"  音频长度: {len(audio)} 样本")
        print(f"  音频时长: {len(audio)/original_sr:.2f} 秒")

        # 如果采样率不是16kHz，进行重采样
        if original_sr != 16000:
            print(f"正在重采样: {original_sr} Hz -> 16000 Hz")
            audio_resampled = librosa.resample(audio, orig_sr=original_sr, target_sr=16000)
        else:
            print("音频已经是16kHz，无需转换")
            audio_resampled = audio

        # 保存为16kHz WAV文件
        sf.write(output_file, audio_resampled, 16000, subtype='PCM_16')

        # 验证输出文件
        audio_check, sr_check = librosa.load(output_file, sr=None)
        print(f"\n转换后音频信息:")
        print(f"  采样率: {sr_check} Hz")
        print(f"  音频长度: {len(audio_check)} 样本")
        print(f"  音频时长: {len(audio_check)/sr_check:.2f} 秒")
        print(f"  文件已保存: {output_file}")

        return True

    except Exception as e:
        print(f"转换失败: {e}")
        return False



def delete_file_os(file_path):
    """
    使用 os.remove() 删除文件
    """
    try:
        if os.path.exists(file_path):
            os.remove(file_path)
            print(f"文件已删除: {file_path}")
            return True
        else:
            print(f"文件不存在: {file_path}")
            return False
    except Exception as e:
        print(f"删除文件失败: {e}")
        return False



def ossUploader(inputWav):

    print(inputWav)
    credentials_provider = oss.credentials.StaticCredentialsProvider(
        access_key_id="LTAI5tCoc2RWa8GjqxuKrufC", # "LTAI5tMQb14jQttyw9C78XnN",     #  LTAI5tCoc2RWa8GjqxuKrufC
        access_key_secret="v81eVoJmOXRMgW32TTHSl0wsDvdpJ6" #"3Xt54SPo2h82VmFE0k1PYYLBrfqhzR"       #   v81eVoJmOXRMgW32TTHSI0wsDvdpJ6
    )

    # 使用SDK的默认配置创建配置对象，并设置认证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 设置配置对象的区域属性，根据用户提供的命令行参数
    cfg.region = "cn-hangzhou"  # "cn-chengdu"


    cfg.endpoint = "http://oss-cn-hangzhou.aliyuncs.com"  #"http://oss-cn-chengdu.aliyuncs.com"

    # 关闭CRC校验
    cfg.disable_upload_crc64_check = True
    cfg.disable_download_crc64_check = True
    print("CRC校验已关闭")


    # 使用上述配置初始化OSS客户端，准备与OSS交互
    client = oss.Client(cfg)

    global progress_save_n
    progress_save_n = 0

    def _progress_fn(n, _written, total):
        global progress_save_n
        progress_save_n += n
        rate = int(100 * (float(_written) / float(total)))
        print('\r{0}% '.format(rate))

    # 创建一个用于上传文件的对象
    uploader = client.uploader()

    filename = os.path.basename(inputWav)

    # 调用方法执行文件上传操作
    result = uploader.upload_file(
        oss.PutObjectRequest(
            bucket="voiceprint-recognition",  # 指定目标存储空间
            key="waveList/" + filename,  # 指定文件在OSS中的名称
            progress_fn=_progress_fn,
        ),
        filepath=inputWav   # 指定本地文件的位置
    )


    print(vars(result))
    status = result.status
    print("   status = ")
    print(status)
    if  status == "OK" :
        fileLink = "https://voiceprint-recognition.oss-cn-hangzhou.aliyuncs.com/waveList/" + filename
        return  fileLink

    else :
        return None



def fileTrans(akId, akSecret, appKey, fileLink) :
    # 地域ID，固定值。
    REGION_ID = "cn-shanghai"
    PRODUCT = "nls-filetrans"
    DOMAIN = "filetrans.cn-shanghai.aliyuncs.com"
    API_VERSION = "2018-08-17"
    POST_REQUEST_ACTION = "SubmitTask"
    GET_REQUEST_ACTION = "GetTaskResult"
    # 请求参数
    KEY_APP_KEY = "appkey"
    KEY_FILE_LINK = "file_link"
    KEY_VERSION = "version"
    KEY_ENABLE_WORDS = "enable_words"
    # 是否开启智能分轨
    KEY_AUTO_SPLIT =  "auto_split"  #"auto_split"
    # 响应参数
    KEY_TASK = "Task"
    KEY_TASK_ID = "TaskId"
    KEY_STATUS_TEXT = "StatusText"
    KEY_RESULT = "Result"
    # 状态值
    STATUS_SUCCESS = "SUCCESS"
    STATUS_RUNNING = "RUNNING"
    STATUS_QUEUEING = "QUEUEING"
    # 创建AcsClient实例
    client = AcsClient(akId, akSecret, REGION_ID)
    # 提交录音文件识别请求
    postRequest = CommonRequest()
    postRequest.set_domain(DOMAIN)
    postRequest.set_version(API_VERSION)
    postRequest.set_product(PRODUCT)
    postRequest.set_action_name(POST_REQUEST_ACTION)
    postRequest.set_method('POST')
    # 新接入请使用4.0版本，已接入（默认2.0）如需维持现状，请注释掉该参数设置。
    # 设置是否输出词信息，默认为false，开启时需要设置version为4.0。
    #task = {KEY_APP_KEY : appKey, KEY_FILE_LINK : fileLink, KEY_VERSION : "4.0", KEY_ENABLE_WORDS : False}
    # 开启智能分轨，如果开启智能分轨，task中设置KEY_AUTO_SPLIT为True。
    task = {KEY_APP_KEY : appKey, KEY_FILE_LINK : fileLink, KEY_VERSION : "4.0", KEY_ENABLE_WORDS : False, KEY_AUTO_SPLIT : True}
    task = json.dumps(task)
    print(task)
    postRequest.add_body_params(KEY_TASK, task)
    taskId = ""
    try :
        postResponse = client.do_action_with_exception(postRequest)
        postResponse = json.loads(postResponse)
        print (postResponse)
        statusText = postResponse[KEY_STATUS_TEXT]
        if statusText == STATUS_SUCCESS :
            print ("录音文件识别请求成功响应！")
            taskId = postResponse[KEY_TASK_ID]
        else :
            print ("录音文件识别请求失败！")
            return   None
    except ServerException as e:
        print (e)
    except ClientException as e:
        print (e)
    # 创建CommonRequest，设置任务ID。
    getRequest = CommonRequest()
    getRequest.set_domain(DOMAIN)
    getRequest.set_version(API_VERSION)
    getRequest.set_product(PRODUCT)
    getRequest.set_action_name(GET_REQUEST_ACTION)
    getRequest.set_method('GET')
    getRequest.add_query_param(KEY_TASK_ID, taskId)
    # 提交录音文件识别结果查询请求
    # 以轮询的方式进行识别结果的查询，直到服务端返回的状态描述符为"SUCCESS"、"SUCCESS_WITH_NO_VALID_FRAGMENT"，
    # 或者为错误描述，则结束轮询。
    statusText = ""
    while True :
        try :
            getResponse = client.do_action_with_exception(getRequest)
            getResponse = json.loads(getResponse)
            print (getResponse)
            statusText = getResponse[KEY_STATUS_TEXT]
            if statusText == STATUS_RUNNING or statusText == STATUS_QUEUEING :
                # 继续轮询
                time.sleep(10)
            else :
                # 退出轮询
                break
        except ServerException as e:
            print (e)
        except ClientException as e:
            print (e)
    if statusText == STATUS_SUCCESS :
        print ("录音文件识别成功！")

        print(getResponse['Result'])
        sentencesList = getResponse['Result']['Sentences']

        return  sentencesList
    else :
        print ("录音文件识别失败！")
        return  None





